package com.lyc.api;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.lyc.constants.Constants;
import com.lyc.utils.HttpClient;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.Type;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.time.LocalDate;
import java.util.*;

/**
 * GroMore广告客户端API。
 */
public class GromoreApiClient {

    private static final Gson policyGson = new Gson();
    private static final Charset UTF_8 = StandardCharsets.UTF_8;
    private static final String HOST = "https://www.csjplatform.com";
    private static final String API_VERSION = "2.0";
    private static final String SIGN_TYPE = "MD5";

    public static int CSJ_APP_ID;
    public static int CSJ_ROLE_ID;
    public static int CSJ_USER_ID;
    public static String CSJ_SECURITY_KEY;

    static {
        loadProperties();
    }

    private static void loadProperties() {
        Properties props = new Properties();
        try (FileInputStream fis = new FileInputStream(new File(Constants.ACCOUNT_PATH + "account.properties"))) {
            props.load(fis);

            CSJ_APP_ID = Integer.parseInt(props.getProperty("CSJ_APP_ID"));
            CSJ_ROLE_ID = Integer.parseInt(props.getProperty("CSJ_ROLE_ID"));
            CSJ_USER_ID = Integer.parseInt(props.getProperty("CSJ_USER_ID"));
            CSJ_SECURITY_KEY = String.valueOf(props.getProperty("CSJ_SECURITY_KEY"));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        Integer ceshi01 = createGromoreRewardRvAdUnit("ceshi01");
        System.out.println("ceshi01 = " + ceshi01);
    }

    /**
     * 批量添加代码位。
     *
     * @param adUnitId GroMore广告位ID
     * @param adSlotList 穿山甲代码位列表
     * @return HTTP响应字符串
     */
    public static String batchAdslot(Integer adUnitId, List<Map<String, Object>> adSlotList) {
        Type type = new TypeToken<List<Map<String, Object>>>(){}.getType();

        Map<String, Object> params = new HashMap<>();
        params.put("ad_unit_id", adUnitId);
        params.put("ad_slot_list", policyGson.toJson(adSlotList, type));

        Map<String, Object> signedParams = setSign(CSJ_USER_ID, CSJ_ROLE_ID, CSJ_SECURITY_KEY, params);

        String response = HttpClient.doPost(HOST + "/union_media/open/api/mediation/batch_adslot", signedParams);
        System.out.println("response = " + response);

        return response;
    }

    /**
     * 创建Gromore激励视频广告位。
     *
     * @param adUnitName 广告位名称。最终的广告位名称是当前月份拼接当前天数，再拼接adUnitName
     * @return 创建的广告位ID
     */
    public static Integer createGromoreRewardRvAdUnit(String adUnitName) {
        LocalDate currentDate = LocalDate.now();
        String currentMonthDay = String.format("%02d%02d", currentDate.getMonthValue(), currentDate.getDayOfMonth());

        Map<String, Object> adUnitMap = new HashMap<>();
        adUnitMap.put("ad_unit_name", currentMonthDay + adUnitName);
        adUnitMap.put("ad_unit_type", 5);

        return createGromoreAdUnit(adUnitMap);
    }

    /**
     * 创建Gromore开屏广告位。
     *
     * @param adUnitName 广告位名称。最终的广告位名称是当前月份拼接当前天数，再拼接adUnitName
     * @return 创建的广告位ID
     */
    public static Integer createGromoreSplashAdUnit(String adUnitName) {
        LocalDate currentDate = LocalDate.now();
        String currentMonthDay = String.format("%02d%02d", currentDate.getMonthValue(), currentDate.getDayOfMonth());

        Map<String, Object> adUnitMap = new HashMap<>();
        adUnitMap.put("ad_unit_name", currentMonthDay + adUnitName);
        adUnitMap.put("ad_unit_type", 3);

        return createGromoreAdUnit(adUnitMap);
    }

    /**
     * 创建Gromore插全屏广告位。
     *
     * @param adUnitName 广告位名称。最终的广告位名称是当前月份拼接当前天数，再拼接adUnitName
     * @return 创建的广告位ID
     */
    public static Integer createGromoreInsertAdUnit(String adUnitName) {
        LocalDate currentDate = LocalDate.now();
        String currentMonthDay = String.format("%02d%02d", currentDate.getMonthValue(), currentDate.getDayOfMonth());

        Map<String, Object> adUnitMap = new HashMap<>();
        adUnitMap.put("ad_unit_name", currentMonthDay + adUnitName);
        adUnitMap.put("ad_unit_type", 10);

        return createGromoreAdUnit(adUnitMap);
    }

    /**
     * 创建Gromore信息流广告位。
     *
     * @param adUnitName 广告位名称。最终的广告位名称是当前月份拼接当前天数，再拼接adUnitName
     * @return 创建的广告位ID
     */
    public static Integer createGromoreNativeAdUnit(String adUnitName) {
        LocalDate currentDate = LocalDate.now();
        String currentMonthDay = String.format("%02d%02d", currentDate.getMonthValue(), currentDate.getDayOfMonth());

        Map<String, Object> adUnitMap = new HashMap<>();
        adUnitMap.put("ad_unit_name", currentMonthDay + adUnitName);
        adUnitMap.put("ad_unit_type", 1);

        return createGromoreAdUnit(adUnitMap);
    }

    /**
     * 创建Gromore横幅广告位。
     *
     * @param adUnitName 广告位名称。最终的广告位名称是当前月份拼接当前天数，再拼接adUnitName
     * @return 创建的广告位ID
     */
    public static Integer createGromoreBannerAdUnit(String adUnitName) {
        LocalDate currentDate = LocalDate.now();
        String currentMonthDay = String.format("%02d%02d", currentDate.getMonthValue(), currentDate.getDayOfMonth());

        Map<String, Object> adUnitMap = new HashMap<>();
        adUnitMap.put("ad_unit_name", currentMonthDay + adUnitName);
        adUnitMap.put("ad_unit_type", 2);

        return createGromoreAdUnit(adUnitMap);
    }

    /**
     * 创建Gromore广告位。
     *
     * @param adUnit 广告位信息
     * @return 创建的广告位ID
     */
    public static Integer createGromoreAdUnit(Map<String, Object> adUnit) {
        Map<String, Object> params = new HashMap<>();
        params.put("app_id", CSJ_APP_ID);

        List<Map<String, Object>> adUnitList = new ArrayList<>();
        adUnitList.add(adUnit);

        Type type = new TypeToken<List<Map<String, Object>>>(){}.getType();
        params.put("ad_unit_list", policyGson.toJson(adUnitList, type));

        Map<String, Object> signedParams = setSign(CSJ_USER_ID, CSJ_ROLE_ID, CSJ_SECURITY_KEY, params);

        String response = HttpClient.doPost(HOST + "/union_media/open/api/mediation/batch_adunit", signedParams);
        System.out.println("Response = " + response);

        Type responseType = new TypeToken<Map<String, Object>>() {}.getType();
        Map<String, Object> responseMap = policyGson.fromJson(response, responseType);

        String code = (String) responseMap.get("code");
        String message = (String) responseMap.get("message");

        if ("100".equals(code) && "Success".equalsIgnoreCase(message)) {
            List<Map<String, Object>> adUnitListResponse = (List<Map<String, Object>>) ((Map<String, Object>) responseMap.get("data")).get("ad_unit_list");
            Number adUnitIdNumber = (Number) adUnitListResponse.get(0).get("ad_unit_id");
            return adUnitIdNumber.intValue();
        } else {
            System.out.println("请求失败。 Code: " + code);
            return -1;
        }
    }

    /**
     * 设置并生成签名参数。
     *
     * @param userId 用户ID
     * @param roleId 角色ID
     * @param params 请求参数
     * @return 包含签名的参数Map
     */
    public static Map<String, Object> setSign(Integer userId, Integer roleId, String securityKey, Map<String, Object> params) {
        long timestamp = System.currentTimeMillis();
        params.put("user_id", userId);
        params.put("role_id", roleId);
        params.put("version", API_VERSION);
        params.put("sign_type", SIGN_TYPE);
        params.put("timestamp", timestamp);

        String signStr = getSignStr(params);
        // System.out.println("Generated sign string: " + signStr);

        String sign = generateSign(signStr, SIGN_TYPE, securityKey);
        params.put("sign", sign);

        return params;
    }

    /**
     * 生成最终的签名字符串。
     *
     * @param content 拼接后的签名字符串
     * @param algorithm 哈希算法（如MD5、SHA-256等）
     * @param securityKey 安全密钥
     * @return 最终的签名字符串
     */
    public static String generateSign(String content, String algorithm, String securityKey) {
        content += securityKey;
        try {
            MessageDigest md = MessageDigest.getInstance(algorithm);
            return bytesToHex(md.digest(content.getBytes(UTF_8)));
        } catch (NoSuchAlgorithmException e) {
            throw new IllegalArgumentException("Unsupported hash algorithm: " + algorithm, e);
        }
    }

    /**
     * 生成签名字符串。
     *
     * @param params 请求参数
     * @return 拼接后的签名字符串
     */
    public static String getSignStr(Map<String, Object> params) {
        List<String> paramStr = new ArrayList<>(params.size());
        for (String key : params.keySet()) {
            paramStr.add(key + "=" + ObjectUtils.toString(params.get(key)));
        }

        Collections.sort(paramStr);
        return StringUtils.join(paramStr, "&");
    }

    /**
     * 将字节数组转换为十六进制字符串。
     *
     * @param bytes 字节数组
     * @return 十六进制字符串
     */
    private static String bytesToHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02x", b));
        }
        return sb.toString();
    }
}
